Skip to content

Fix outstanding frontend_path issues#6328

Open
masenf wants to merge 5 commits intomainfrom
masenf/fx-frontend-path
Open

Fix outstanding frontend_path issues#6328
masenf wants to merge 5 commits intomainfrom
masenf/fx-frontend-path

Conversation

@masenf
Copy link
Copy Markdown
Collaborator

@masenf masenf commented Apr 14, 2026

Summary

Fixes outstanding issues with the frontend_path config option and adds comprehensive integration tests to prevent regressions.

When frontend_path is set (e.g. frontend_path="/app"), the Reflex app is served from a subpath instead of the root. This PR ensures that assets, stylesheets, links, redirects, uploads, on_load events, and 404 pages all work correctly under a configured frontend_path.

Changes

  • Integration tests (tests/integration/tests_playwright/test_frontend_path.py): Comprehensive playwright tests covering links (static and dynamic routes), redirects (event handler and on_load), assets (local and shared), uploaded files (rx.get_upload_url), CSS url() references, on_load event firing, and 404 pages. Tests are parametrized over dev/prod mode and with/without frontend_path.
  • Shared asset fix (reflex/assets.py): rx.asset(shared=True) now calls prepend_frontend_path on its return value, matching the existing behavior for local assets.
  • testing.py: Fix AppHarnessProd to locate 404.html under the frontend_path subdirectory when set, matching real prod deployment behavior.
  • CI workflow (.github/workflows/integration_app_harness.yml): Run playwright tests in a separate job from other integration tests. The pytest-playwright plugin keeps an asyncio event loop running on the main thread for the session, which is incompatible with pytest-asyncio tests in the same process.

Closes

Supersedes

Test plan

  • uv run pytest tests/integration/tests_playwright/test_frontend_path.py -v passes in both dev and prod modes, with and without frontend_path
  • Existing integration tests still pass: uv run pytest tests/integration --ignore=tests/integration/tests_playwright -v
  • Playwright tests are isolated from pytest-asyncio tests in CI

masenf added 3 commits April 13, 2026 16:36
* also initialize vite.config.js during compile, in case user has set a
  different runtime frontend path
* remove assetsDir workaround (base handles this case)
Add `prepend_frontend_path` to `rx.Config` to make it easy to handle the
contract in current and future APIs.

Use `prepend_frontend_path` in:
  * rx.get_upload_url
  * rx.asset
  * vite config
  * react router config
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 14, 2026

Merging this PR will not alter performance

✅ 9 untouched benchmarks


Comparing masenf/fx-frontend-path (12cfd39) with main (4c53848)

Open in CodSpeed

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 14, 2026

Greptile Summary

This PR fixes frontend_path subpath deployments by introducing a central prepend_frontend_path utility on Config and wiring it through assets, Vite config, React Router basename, static file mounts, and the prod test harness. It also replaces the assetsDir workaround in the Vite template with the proper base option, and separates playwright tests into their own CI job to avoid event-loop conflicts with pytest-asyncio.

Confidence Score: 5/5

Safe to merge — all remaining findings are P2 style/edge-case items that don't affect any realistic user configuration.

Both findings are P2: a commented-out decorator (style/rule violation) and a double-slash edge case in prepend_frontend_path that only triggers when frontend_path="/" — a configuration no user would intentionally set. The core logic is correct, well-refactored, and backed by comprehensive integration tests covering dev/prod × prefix/no-prefix.

packages/reflex-base/src/reflex_base/config.py — the prepend_frontend_path utility could be tightened to strip before the truthiness check.

Important Files Changed

Filename Overview
packages/reflex-base/src/reflex_base/config.py Adds prepend_frontend_path utility method centralizing all subpath logic; has an edge case where frontend_path="/" produces double-slash paths.
packages/reflex-base/src/reflex_base/compiler/templates.py Replaces the workaround assetsDir: "{base}assets".slice(1) with Vite's canonical base option — cleaner and more correct for subpath deployments.
reflex/assets.py Both local and shared rx.asset return values now call prepend_frontend_path, fixing shared-asset URLs under a configured frontend_path.
reflex/testing.py AppHarnessProd correctly computes the 404 page path and frontend_url including the configured prefix using the new prepend_frontend_path utility.
reflex/utils/frontend_skeleton.py Both _update_react_router_config (basename) and _compile_vite_config (base) now use prepend_frontend_path, eliminating duplicated path-assembly logic.
reflex/utils/exec.py Mount path now uses prepend_frontend_path; functionally equivalent because Starlette internally strips trailing slashes from Mount paths.
reflex/app.py Adds a recompile of the Vite config during the build pipeline so environment-variable-driven frontend_path is always picked up; step counter correctly bumped to 8.
tests/integration/tests_playwright/test_frontend_path.py Comprehensive playwright tests parametrized over dev/prod and with/without prefix; has a commented-out @pytest.mark.ignore_console_error decorator that should be removed.
.github/workflows/integration_app_harness.yml Correctly splits playwright tests into their own job to avoid event-loop conflicts with pytest-asyncio; the non-playwright job keeps its split_index matrix while playwright omits it.
tests/units/test_prerequisites.py Unit test expectations updated from assetsDir to base to match the new Vite config format; all three cases (empty, /test, /test/) are covered.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[frontend_path config\ne.g. '/prefix'] --> B[prepend_frontend_path\nConfig method]

    B --> C[Vite config\nbase: '/prefix/']
    B --> D[React Router\nbasename: '/prefix/']
    B --> E[Starlette Mount\n'/prefix/']
    B --> F[rx.asset local\n'/prefix/image.png']
    B --> G[rx.asset shared\n'/prefix/external/...']
    B --> H[AppHarnessProd\n404 path + frontend_url]

    C --> I[Vite builds assets\nwith correct public URLs]
    D --> J[Client-side nav\nstays under /prefix]
    E --> K[Static file server\nserves from /prefix]
    F & G --> L[Asset URLs\nresolvable by browser]
    H --> M[Test harness\nserves 404.html correctly]
Loading

Reviews (2): Last reviewed commit: "fix frontend path for shared assets" | Re-trigger Greptile

Comment thread tests/integration/tests_playwright/test_frontend_path.py
masenf added 2 commits April 14, 2026 18:09
playwright uses a session scope fixture which creates an event loop for the
session, so subsequent tests using pytest_asyncio fixture cannot start their
own loop and fail
include updated test case
@masenf
Copy link
Copy Markdown
Collaborator Author

masenf commented Apr 15, 2026

@greptile-apps re-review this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants